package services

import (
	"errors"
	"time"

	"github.com/cynhard/ticket-system/internal/models"
	"gorm.io/gorm"
)

// TicketService 工单服务接口
type TicketService interface {
	CreateTicket(title, description, priority string, creatorID uint) (*models.Ticket, error)
	GetTicketByID(id uint) (*models.Ticket, error)
	ListTickets(page, pageSize int, status string) ([]*models.Ticket, int64, error)
	ListUserTickets(userID uint, page, pageSize int) ([]*models.Ticket, int64, error)
	ListAssignedTickets(assigneeID uint, page, pageSize int) ([]*models.Ticket, int64, error)
	AssignTicket(ticketID, assigneeID uint) (*models.Ticket, error)
	TakeTicket(ticketID, userID uint) (*models.Ticket, error)
	ResolveTicket(ticketID uint) (*models.Ticket, error)
	CloseTicket(ticketID uint) (*models.Ticket, error)
	AddComment(ticketID, userID uint, content string) (*models.Comment, error)
	ListComments(ticketID uint) ([]*models.Comment, error)
	GetTicketMetrics() (map[string]interface{}, error)
}

// TicketServiceImpl 工单服务实现
type TicketServiceImpl struct {
	db *gorm.DB
}

// NewTicketService 创建工单服务
func NewTicketService(db *gorm.DB) TicketService {
	return &TicketServiceImpl{
		db: db,
	}
}

// CreateTicket 创建工单
func (s *TicketServiceImpl) CreateTicket(title, description, priority string, creatorID uint) (*models.Ticket, error) {
	// 验证优先级
	if priority != models.PriorityLow && priority != models.PriorityMedium && priority != models.PriorityHigh {
		priority = models.PriorityMedium // 默认为中优先级
	}

	ticket := &models.Ticket{
		Title:       title,
		Description: description,
		Status:      models.StatusOpen,
		Priority:    priority,
		CreatorID:   creatorID,
	}

	result := s.db.Create(ticket)
	if result.Error != nil {
		return nil, result.Error
	}

	return ticket, nil
}

// GetTicketByID 根据ID获取工单
func (s *TicketServiceImpl) GetTicketByID(id uint) (*models.Ticket, error) {
	var ticket models.Ticket
	result := s.db.Preload("Creator").Preload("Assignee").Preload("Comments.User").First(&ticket, id)
	if result.Error != nil {
		return nil, result.Error
	}
	return &ticket, nil
}

// ListTickets 获取工单列表
func (s *TicketServiceImpl) ListTickets(page, pageSize int, status string) ([]*models.Ticket, int64, error) {
	var tickets []*models.Ticket
	var total int64

	offset := (page - 1) * pageSize
	query := s.db.Model(&models.Ticket{})

	// 如果指定了状态，则添加状态筛选
	if status != "" {
		query = query.Where("status = ?", status)
	}

	// 获取总数
	query.Count(&total)

	// 获取分页数据
	result := query.Preload("Creator").Preload("Assignee").
		Offset(offset).Limit(pageSize).
		Order("created_at DESC").
		Find(&tickets)

	if result.Error != nil {
		return nil, 0, result.Error
	}

	return tickets, total, nil
}

// ListUserTickets 获取用户的工单列表
func (s *TicketServiceImpl) ListUserTickets(userID uint, page, pageSize int) ([]*models.Ticket, int64, error) {
	var tickets []*models.Ticket
	var total int64

	offset := (page - 1) * pageSize
	query := s.db.Model(&models.Ticket{}).Where("creator_id = ?", userID)

	// 获取总数
	query.Count(&total)

	// 获取分页数据
	result := query.Preload("Creator").Preload("Assignee").
		Offset(offset).Limit(pageSize).
		Order("created_at DESC").
		Find(&tickets)

	if result.Error != nil {
		return nil, 0, result.Error
	}

	return tickets, total, nil
}

// ListAssignedTickets 获取分配给指定用户的工单列表
func (s *TicketServiceImpl) ListAssignedTickets(assigneeID uint, page, pageSize int) ([]*models.Ticket, int64, error) {
	var tickets []*models.Ticket
	var total int64

	offset := (page - 1) * pageSize
	query := s.db.Model(&models.Ticket{}).Where("assignee_id = ?", assigneeID)

	// 获取总数
	query.Count(&total)

	// 获取分页数据
	result := query.Preload("Creator").Preload("Assignee").
		Offset(offset).Limit(pageSize).
		Order("created_at DESC").
		Find(&tickets)

	if result.Error != nil {
		return nil, 0, result.Error
	}

	return tickets, total, nil
}

// AssignTicket 分配工单
func (s *TicketServiceImpl) AssignTicket(ticketID, assigneeID uint) (*models.Ticket, error) {
	ticket, err := s.GetTicketByID(ticketID)
	if err != nil {
		return nil, err
	}

	// 检查是否可分配
	if ticket.Status != models.StatusOpen && ticket.Status != models.StatusAssigned {
		return nil, errors.New("只有开放或已分配的工单可以重新分配")
	}

	// 检查分配的用户是否存在
	var user models.User
	result := s.db.First(&user, assigneeID)
	if result.Error != nil {
		return nil, errors.New("分配的用户不存在")
	}

	// 分配工单
	now := time.Now()
	ticket.AssigneeID = &assigneeID
	ticket.Assignee = &user
	ticket.Status = models.StatusAssigned
	ticket.AssignedAt = &now

	result = s.db.Save(ticket)
	if result.Error != nil {
		return nil, result.Error
	}

	return ticket, nil
}

// TakeTicket 获取工单
func (s *TicketServiceImpl) TakeTicket(ticketID, userID uint) (*models.Ticket, error) {
	ticket, err := s.GetTicketByID(ticketID)
	if err != nil {
		return nil, err
	}

	// 检查是否可获取
	if ticket.Status != models.StatusOpen {
		return nil, errors.New("只有开放的工单可以被获取")
	}

	// 检查获取的用户是否存在
	var user models.User
	result := s.db.First(&user, userID)
	if result.Error != nil {
		return nil, errors.New("获取的用户不存在")
	}

	// 获取工单
	now := time.Now()
	ticket.AssigneeID = &userID
	ticket.Assignee = &user
	ticket.Status = models.StatusAssigned
	ticket.AssignedAt = &now

	result = s.db.Save(ticket)
	if result.Error != nil {
		return nil, result.Error
	}

	return ticket, nil
}

// ResolveTicket 解决工单
func (s *TicketServiceImpl) ResolveTicket(ticketID uint) (*models.Ticket, error) {
	ticket, err := s.GetTicketByID(ticketID)
	if err != nil {
		return nil, err
	}

	// 检查是否可解决
	if ticket.Status != models.StatusAssigned {
		return nil, errors.New("只有已分配的工单可以被解决")
	}

	// 标记为已解决
	now := time.Now()
	ticket.Status = models.StatusResolved
	ticket.ResolvedAt = &now

	// 如果已分配且有分配时间，计算处理时长
	if ticket.AssignedAt != nil {
		ticket.HandlingTime = int64(now.Sub(*ticket.AssignedAt).Seconds())
	}

	result := s.db.Save(ticket)
	if result.Error != nil {
		return nil, result.Error
	}

	return ticket, nil
}

// CloseTicket 关闭工单
func (s *TicketServiceImpl) CloseTicket(ticketID uint) (*models.Ticket, error) {
	ticket, err := s.GetTicketByID(ticketID)
	if err != nil {
		return nil, err
	}

	// 检查是否可关闭（任何状态都可以关闭）
	now := time.Now()
	ticket.Status = models.StatusClosed
	ticket.ClosedAt = &now

	result := s.db.Save(ticket)
	if result.Error != nil {
		return nil, result.Error
	}

	return ticket, nil
}

// AddComment 添加评论
func (s *TicketServiceImpl) AddComment(ticketID, userID uint, content string) (*models.Comment, error) {
	// 检查工单是否存在
	var ticket models.Ticket
	result := s.db.First(&ticket, ticketID)
	if result.Error != nil {
		return nil, errors.New("工单不存在")
	}

	// 检查用户是否存在
	var user models.User
	result = s.db.First(&user, userID)
	if result.Error != nil {
		return nil, errors.New("用户不存在")
	}

	// 创建评论
	comment := &models.Comment{
		Content:  content,
		TicketID: ticketID,
		UserID:   userID,
	}

	result = s.db.Create(comment)
	if result.Error != nil {
		return nil, result.Error
	}

	// 加载用户信息
	s.db.Preload("User").First(comment, comment.ID)

	return comment, nil
}

// ListComments 获取工单评论列表
func (s *TicketServiceImpl) ListComments(ticketID uint) ([]*models.Comment, error) {
	var comments []*models.Comment

	result := s.db.Where("ticket_id = ?", ticketID).
		Preload("User").
		Order("created_at ASC").
		Find(&comments)

	if result.Error != nil {
		return nil, result.Error
	}

	return comments, nil
}

// GetTicketMetrics 获取工单统计信息
func (s *TicketServiceImpl) GetTicketMetrics() (map[string]interface{}, error) {
	metrics := make(map[string]interface{})

	// 总工单数
	var totalTickets int64
	s.db.Model(&models.Ticket{}).Count(&totalTickets)
	metrics["total_tickets"] = totalTickets

	// 按状态统计
	var openCount, assignedCount, resolvedCount, closedCount int64
	s.db.Model(&models.Ticket{}).Where("status = ?", models.StatusOpen).Count(&openCount)
	s.db.Model(&models.Ticket{}).Where("status = ?", models.StatusAssigned).Count(&assignedCount)
	s.db.Model(&models.Ticket{}).Where("status = ?", models.StatusResolved).Count(&resolvedCount)
	s.db.Model(&models.Ticket{}).Where("status = ?", models.StatusClosed).Count(&closedCount)

	statusStats := map[string]int64{
		models.StatusOpen:     openCount,
		models.StatusAssigned: assignedCount,
		models.StatusResolved: resolvedCount,
		models.StatusClosed:   closedCount,
	}
	metrics["status_stats"] = statusStats

	// 按优先级统计
	var lowCount, mediumCount, highCount int64
	s.db.Model(&models.Ticket{}).Where("priority = ?", models.PriorityLow).Count(&lowCount)
	s.db.Model(&models.Ticket{}).Where("priority = ?", models.PriorityMedium).Count(&mediumCount)
	s.db.Model(&models.Ticket{}).Where("priority = ?", models.PriorityHigh).Count(&highCount)

	priorityStats := map[string]int64{
		models.PriorityLow:    lowCount,
		models.PriorityMedium: mediumCount,
		models.PriorityHigh:   highCount,
	}
	metrics["priority_stats"] = priorityStats

	// 平均处理时间
	var avgHandlingTime float64
	s.db.Model(&models.Ticket{}).Where("handling_time > 0").Select("AVG(handling_time)").Row().Scan(&avgHandlingTime)
	metrics["avg_handling_time"] = avgHandlingTime

	// 每个月创建的工单数量（最近12个月）
	var monthlyStats []struct {
		Month string
		Count int64
	}
	
	// 这里的SQL语法可能需要根据实际使用的数据库调整
	query := `
		SELECT 
			DATE_FORMAT(created_at, '%Y-%m') as month,
			COUNT(*) as count
		FROM 
			tickets
		WHERE 
			created_at >= DATE_SUB(NOW(), INTERVAL 12 MONTH)
		GROUP BY 
			DATE_FORMAT(created_at, '%Y-%m')
		ORDER BY 
			month ASC
	`
	s.db.Raw(query).Scan(&monthlyStats)
	metrics["monthly_stats"] = monthlyStats

	return metrics, nil
} 